package com.cskaoyan.shiro;

import com.cskaoyan.bean.admin.*;
import com.cskaoyan.mapper.admin.AdminMapper;
import com.cskaoyan.mapper.admin.PermissionMapper;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 类<code>Doc</code>用于：TODO
 *
 * @author Acher
 * @version 1.0
 * @date 2021-10-20
 */
@Component
public class CustomRealm extends AuthorizingRealm {

    @Autowired
    AdminMapper adminMapper;
    @Autowired
    PermissionMapper permissionMapper;

    // 建议认证写前面 👉 因为顺序是链式调用 👈 不是的!因为是先认证,后授权.就算doGetAuthenticationInfo 放在doGetAuthorizationInfo后面也是可以的.
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 提供认证信息
        // 参数AuthenticationToken 来源于 subject.login的时候携带的参数
        // 登录时传入用户名
        String username = ((UsernamePasswordToken) token)
                .getUsername();
        AdminExample example = new AdminExample();
        example.createCriteria().andUsernameEqualTo(username);
        // 根据username通过数据库查询密码
        List<Admin> admins = adminMapper.selectByExample(example);
        if (admins == null || admins.size() == 0)
            return null;
        Admin admin = admins.get(0);
        String credential = admin.getPassword();
        // param1：Principal信息（用户信息），认证成功后维护在session中
        // param2：credentials，凭据
        // param3：realm的名称
        return new SimpleAuthenticationInfo(admin, credential, this.getName());
    }

    // 授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //获得用户信息principal → 上面返回认证信息的第一个参数里维护了用户信息
        Admin admin = (Admin) principals.getPrimaryPrincipal();
        Integer id = admin.getId();
        // 根据用户信息获得权限信息 👉 查询数据库
        List<String> permissions = queryDb(id);
        // 给用户增加对应的权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addStringPermissions(permissions);
        return simpleAuthorizationInfo;
    }

    private List<String> queryDb(Integer id) {
        // 根据adminId获取rolesId数组 👉 根据rolesId获取permissionId
        Admin admin = adminMapper.selectByPrimaryKey(id);
        Integer[] roleIds = admin.getRoleIds();// List<String>
        PermissionExample example = new PermissionExample();
        example.createCriteria().andRoleIdIn(Arrays.asList(roleIds));
        List<Permission> permissionList = permissionMapper.selectByExample(example);
        List<String> permissions = new ArrayList<>();
        permissionList.forEach(item -> permissions.add(item.getPermission()));
        return permissions;
    }
}
